package com.niit.order.web;


import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import com.niit.feign.pojo.User;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("/consumer")
public class HystrixConsumerController {

    @Autowired
    private RestTemplate restTemplate;


    /**
     * 请求合并案例
     * @param id
     * @return
     */
    @GetMapping("/findUser/{id}")
    @HystrixCollapser(
            batchMethod = "findAll", collapserProperties = {
            @HystrixProperty(name = "timerDelayInMilliseconds", value = "100")
    })
    public User findUser(@PathVariable("id") String id) {
        return null;
    }

    /**
     * 请求合并案例
     * @param ids
     * @return
     */
    @HystrixCommand(fallbackMethod = "findAllFallback")
    public List<User> findAll(List<String> ids) {
        User[] forObject = restTemplate.getForObject("http://userservice/user/findAll/{1}", User[].class, StringUtils.join(ids, ","));
        assert forObject != null;
        return Arrays.asList(forObject);
    }

    public List<User> findAllFallback(List<String> ids) {
        ArrayList<User> users = new ArrayList<>();
        for (String id : ids) {
            User user = new User();
            user.setId(id);
            users.add(user);
        }
        return users;
    }

    /**
     * 测试缓存清除功能
     *
     * @param user
     * @return
     */
    @CacheRemove(commandKey = "getUserById")
    @HystrixCommand(fallbackMethod = "updateFallback")
    @PostMapping("/update")
    public User update(@CacheKey("id") @RequestBody User user) {
        return restTemplate.postForObject("http://userservice/user/update", user, User.class);
    }

    public User updateFallback(User user) {
        user.setUsername("更新失败!");
        return user;
    }


    /**
     * 获取用户信息 开启缓存
     *
     * @param id
     * @return
     */
    @GetMapping("/user/{id}")
    @HystrixCommand(fallbackMethod = "getUserInfoFallback")
    @CacheResult(cacheKeyMethod = "cacheKey")
    public User getUserById(@PathVariable("id") @CacheKey String id) {

        String url = "http://userservice/user/" + id;
        return restTemplate.getForObject(url, User.class);
    }

    public String cacheKey(String id) {
        return id;
    }

    public User getUserInfoFallback(String id) {
        User user = new User();
        user.setUsername("服务器故障");
        user.setAddress("郑州");
        user.setId(id);
        return user;
    }

    /**
     * 测试 HystrixCommand注解各种属性
     *
     * @param param
     * @return
     */
    @GetMapping("/hystrix/{param}")
    @HystrixCommand(fallbackMethod = "showAppInfoFallback",
            ignoreExceptions = {IOException.class, FileNotFoundException.class},
            commandKey = "showAppInfo",
            groupKey = "userGroup",
            threadPoolKey = "showAppInfoThread"
    )
    @CacheResult
    public String showAppInfo(@PathVariable("param") String param) {
        //通过RestTemplate查询用户信息 使用服务名代替ip和端口号
        String url = "http://userservice/provider/hystrix/" + param;
        return restTemplate.getForObject(url, String.class);
    }


    /**
     * 服务降级方法
     *
     * @param param     源方法传入的参数
     * @param exception 接收到的异常信息
     * @return 和源方法的返回值类型保持一致
     */
    @HystrixCommand(fallbackMethod = "showAppInfoFallbackEnd")
    public String showAppInfoFallback(String param, Throwable exception) {

//        String url = "http://userservice/hystrix/" + param + "abc " + exception.getMessage();
//        return restTemplate.getForObject(url, String.class);

        return "服务器繁忙,请稍后再试o(╥﹏╥)o" + param;
    }


    /**
     * 终极服务降级方法
     *
     * @param param 源方法传入的参数
     * @return 和源方法的返回值类型保持一致
     */

    public String showAppInfoFallbackEnd(String param) {
        return "最终降级方法,逻辑稳定..." + param;
    }


}
